// Tierless
// Copyright © 2010 Alphora
// This file is licensed under a modified BSD-license (see tierless_license.txt).
using System;
using System.Data;

namespace Tierless.Infrastructure.Data
{
	/// <summary>
	/// Represents a parameter to a command.
	/// </summary>
	public class Param
	{
		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="modifier">Indicates whether the parameter is input, output, or both.</param>
		/// <param name="type">The type of the parameter.</param>
		/// <param name="tempValue">The initial value for the parameter.</param>
		public Param(string name, ParameterDirection modifier, Type type, object tempValue)
		{
			Name = name;
			Modifier = modifier;
			_type = type;
			SetValue(tempValue);
		}
		
		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="modifier">Indicates whether the parameter is input, output, or both.</param>
		/// <param name="tempValue">The initial value for the parameter.</param>
		/// <remarks>
		///	The type of the parameter is inferred from the initial value, if possible.
		/// </remarks>
		public Param(string name, ParameterDirection modifier, object tempValue) : this(name, modifier, null, tempValue) { }


		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="modifier">Indicates whether the parameter is input, output, or both.</param>
		/// <param name="type">The type of the parameter.</param>
		public Param(string name, ParameterDirection modifier, Type type) : this(name, modifier, type, null) { }

		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="type">The type of the parameter.</param>
		/// <param name="tempValue">The initial value for the parameter.</param>
		/// <remarks>
		/// The modifier is assumed to be ParameterDirection.Input.
		/// </remarks>
		public Param(string name, Type type, object tempValue) : this(name, ParameterDirection.Input, type, tempValue) { }

		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="tempValue">The initial value for the parameter.</param>
		/// <remarks>
		/// The modifier is assumed to be ParameterDirection.Input.
		/// The type of the parameter is inferred from the initial value, if possible.
		/// </remarks>
		public Param(string name, object tempValue) : this(name, null, tempValue) { }

		/// <summary>
		/// Creates a new instance of a parameter.
		/// </summary>
		/// <param name="name">The name of the parameter.</param>
		/// <param name="type">The type of the parameter.</param>
		/// <remarks>
		/// The modifier is assumed to be ParameterDirection.Input.
		/// </remarks>
		public Param(string name, Type type) : this(name, type, null) { }

		/// <summary>
		/// Gets or sets the name of the parameter.
		/// </summary>
		public string Name { get; set; }

		/// <summary>
		/// Gets or sets the modifier for the parameter.
		/// </summary>
		public ParameterDirection Modifier { get; set; }

		private Type _type;
		/// <summary>
		/// Gets or sets the type of the parameter.
		/// </summary>
		public Type Type
		{
			get { return _type; }
			set { _type = value; }
		}
		
		private object _value;
		/// <summary>
		/// Gets or sets the value of the parameter.
		/// </summary>
		/// <remarks>
		/// The type of the parameter is inferred from the value, if possible.
		/// </remarks>
		public object Value
		{
			get { return _value; }
			set { SetValue(value); }
		}
		
		private void SetValue(object tempValue)
		{
			_value = tempValue;
			if ((_value != null) && (_value != DBNull.Value))
				_type = _value.GetType();
		}
	}
}
